package cn.itsource.pethome.config;

import cn.itsource.pethome.annotation.PreAuthorize;
import cn.itsource.pethome.jwt.JwtUtils;
import cn.itsource.pethome.jwt.Payload;
import cn.itsource.pethome.jwt.PayloadData;
import cn.itsource.pethome.org.mapper.EmployeeMapper;
import cn.itsource.pethome.util.RsaUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.security.PublicKey;
import java.util.Date;
import java.util.Set;

/**
 * springmvc的拦截器
 *
 */
//往spring容器里面注册bean
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private EmployeeMapper employeeMapper;
    @Value("${jwt.rsa.pub}")
    private String pub;
    @Override                                                                          //它可以得到你当前执行的controller方法
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //做什么事情
        //1.获取请求头
        String token = request.getHeader("token");
        //2.校验token
        if(!StringUtils.isEmpty(token)){//不为null才会进来
            //3.根据token获取redis的值
//            Object userinfo = redisTemplate.opsForValue().get(token);

            //得到公钥
            PublicKey publicKey = RsaUtils.getPublicKey(JwtUtils.class.getClassLoader().getResource(pub).getFile());
            //解密
            Payload<PayloadData> userinfo = JwtUtils.getInfoFromToken(token, publicKey, PayloadData.class);

            if(userinfo != null){
                //刷新token
                Date expiration = userinfo.getExpiration();
                //刷新时间
                DateTime refreshTime = new DateTime(expiration).minusMinutes(5);
                //当前时间在刷新时间之后就要刷新一把
                if(refreshTime.isBefore(DateTime.now())){
                    //重新登录刷新token          response.getWriter().write("{\"success\":false,\"message\":\"noLogin\"}");
                    return false;
                }
                PayloadData payloadData = userinfo.getUserInfo();
                if(payloadData.getUser() != null){//普通用户
                    return true;
                }
                Set<String> permissions = payloadData.getPermissions();
                // 6.通过handler 得到对应的方法
                if(!(handler instanceof HandlerMethod)){
                    return true;
                }
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                // 7.获取方法上面的注解  并解析注解
                PreAuthorize methodAnnotation = handlerMethod.getMethodAnnotation(PreAuthorize.class);
                if(methodAnnotation == null){
                   return true;
                }
                String sn = methodAnnotation.value();
                // 8.将数据库里 sn 和 获取到的接口的注解进行匹配
                if(permissions.contains(sn)){//如果有 返回true 如果没有false
                    return true;
                }
                //2.1如果获取不到值返回错误信息
                //3.1拿不到 登录失效返回错误信息
                response.setCharacterEncoding("UTF-8");//如果返回有中文就必须设置 防止乱码
                response.setContentType("application/json;charset=utf-8");//设置返回响应的格式
                PrintWriter writer = response.getWriter();//向外部写数据
                writer.print("{\"success\":false,\"msg\":\"你不是vip,请充值\"}");//json数据格式
                writer.flush();
                writer.close();


                // 9.相同放行
                return false;
            }
        }
        //2.1如果获取不到值返回错误信息
        //3.1拿不到 登录失效返回错误信息
        response.setCharacterEncoding("UTF-8");//如果返回有中文就必须设置 防止乱码
        response.setContentType("application/json;charset=utf-8");//设置返回响应的格式
        PrintWriter writer = response.getWriter();//向外部写数据
        writer.print("{\"success\":false,\"msg\":\"noLogin\"}");//json数据格式
        writer.flush();
        writer.close();
        return false;
        //疑问  这里返回false  前端根本就不知道你通过还是没有通过   没有办法去跳转的登录页面
    }


    public void old(){
//        //做什么事情
//        //1.获取请求头
//        String token = request.getHeader("token");
//        //2.校验token
//        if(!StringUtils.isEmpty(token)){//不为null才会进来
//            //3.根据token获取redis的值
//            Object userinfo = redisTemplate.opsForValue().get(token);
//            if(userinfo != null){
//                //3.2拿不到 刷新token过期时间，放行
//                redisTemplate.opsForValue().set(token,userinfo,30, TimeUnit.MINUTES);
//                //todo 拦截所有的路径  判断当前人  是否有当前接口的权限
//
//                // 1.从redis 里面取 logininfo
//                Logininfo logininfo =  (Logininfo)userinfo;
//                // 2.通过employee 的查询  可以得到当前登录人
//                // 3.通过中间表查询到 角色id
//                // 4.根据角色去查询中间表 角色和权限的中间表  得到权限的id
//                // 5.得到权限的sn
//                List<String> sns = employeeMapper.selectSn(logininfo.getId());
//                // 6.通过handler 得到对应的方法
//                HandlerMethod handlerMethod = (HandlerMethod) handler;
//                // 7.获取方法上面的注解  并解析注解
//                PreAuthorize methodAnnotation = handlerMethod.getMethodAnnotation(PreAuthorize.class);
//                if(methodAnnotation == null){
//                    return true;
//                }
//                String sn = methodAnnotation.value();
//                // 8.将数据库里 sn 和 获取到的接口的注解进行匹配
//                if(sns.contains(sn)){//如果有 返回true 如果没有false
//                    return true;
//                }
//                //2.1如果获取不到值返回错误信息
//                //3.1拿不到 登录失效返回错误信息
//                response.setCharacterEncoding("UTF-8");//如果返回有中文就必须设置 防止乱码
//                response.setContentType("application/json;charset=utf-8");//设置返回响应的格式
//                PrintWriter writer = response.getWriter();//向外部写数据
//                writer.print("{\"success\":false,\"msg\":\"你不是vip,请充值\"}");//json数据格式
//                writer.flush();
//                writer.close();
//
//
//                // 9.相同放行
//                return false;
//            }
//        }
//        //2.1如果获取不到值返回错误信息
//        //3.1拿不到 登录失效返回错误信息
//        response.setCharacterEncoding("UTF-8");//如果返回有中文就必须设置 防止乱码
//        response.setContentType("application/json;charset=utf-8");//设置返回响应的格式
//        PrintWriter writer = response.getWriter();//向外部写数据
//        writer.print("{\"success\":false,\"msg\":\"noLogin\"}");//json数据格式
//        writer.flush();
//        writer.close();
//        return false;
        //疑问  这里返回false  前端根本就不知道你通过还是没有通过   没有办法去跳转的登录页面
    }
}
